/**
 * parser - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    $.parser = {
        /**
         * 解析data-options属性
         *
         * 调用例子:
         * $.parser.parseOptions(target);
         * $.parser.parseOptions(target, ['id','title','width',{fit:'boolean',border:'boolean'},{min:'number'}]);
         */
        parseOptions: function(target, properties) {
            var t = $(target);
            var options = {};

            var s = $.trim(t.attr('data-options'));
            if (s) {
                if (s.substring(0, 1) == '[') { //对象数组支持
                    var arrayOptions = (new Function('return ' + s))();
                    $.each(arrayOptions, function(i, v) {
                        $.extend(options, v);
                    });
                } else {
                    if (s.substring(0, 1) != '{') {
                        s = '{' + s + '}';
                    }
                    options = (new Function('return ' + s))();
                }
            }

            if (properties) {
                var opts = {};
                for (var i = 0; i < properties.length; i++) {
                    var pp = properties[i];
                    if (typeof pp == 'string') {
                        if (pp == 'width' || pp == 'height' || pp == 'left' || pp == 'top') {
                            opts[pp] = parseInt(target.style[pp]) || undefined;
                        } else {
                            opts[pp] = t.attr(pp);
                        }
                    } else {
                        for (var name in pp) {
                            var type = pp[name];
                            if (type == 'boolean') {
                                opts[name] = t.attr(name) ? (t.attr(name) == 'true') : undefined;
                            } else if (type == 'number') {
                                opts[name] = t.attr(name) == '0' ? 0 : parseFloat(t.attr(name)) || undefined;
                            }
                        }
                    }
                }
                $.extend(options, opts);
            }
            return options;
        }
    };

    //设置box model宽度
    $.fn._outerWidth = function(width) {
        if (width == undefined) {
            return this.outerWidth() || 0;
        }
        return this.each(function() {
            $(this).width(width - ($(this).outerWidth() - $(this).width()));
        });
    };

    //设置box model高度
    $.fn._outerHeight = function(height) {
        if (height == undefined) {
            return this.outerHeight() || 0;
        }
        return this.each(function() {
            $(this).height(height - ($(this).outerHeight() - $(this).height()));
        });
    };
})(jQuery);/**
 * mask - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    //设置大小
    function setSize(target) {
        var state = $.data(target, 'mask');
        if (state) {
            var opts = state.options;
            var mask = state.mask;
            var maskMsg = state.maskMsg;
            var cc = $(target);

            var css = {
                left: 0,
                top: 0,
                width: cc.outerWidth(),
                height: cc.outerHeight()
            };

            if (cc[0].tagName == 'BODY') {
                $.extend(css, getPageArea());
            }

            mask.css(css);
            maskMsg.css({
                left: (mask.outerWidth() - maskMsg.outerWidth()) / 2,
                top: (mask.outerHeight() - maskMsg.outerHeight()) / 2
            });
        }
    }

   	//构建遮罩层
    function init(target) {
        var state = $.data(target, 'mask');
        var opts = state.options;
        var cc = $(target).css('zoom', '1'); //ie6 bug

        var mask = $('<div class="x-mask"></div>').css('display', 'block').appendTo(cc);
        var maskMsg = $('<div class="x-mask-msg"></div>').html(opts.msg).css('display', 'block').appendTo(cc);

        state.mask = mask;
        state.maskMsg = maskMsg;
    }

    //绑定事件
    function bindEvents(target) {
        $(window).resize(function() {
            setSize(target); //resize时mask可能已经destroy了
        });
    }

    //显示遮罩层
    function show(target) {
        var state = $.data(target, 'mask');
        var mask = state.mask;
        var maskMsg = state.maskMsg;
        $('select:not([disabled])', target).addClass('x-mask-disabled-select').attr('disabled', 'disabled'); //ie6下的select的z-index bug
        mask.css('display', 'block');
        maskMsg.css('display', 'block');
        setSize(target);
        state.showCount++;
    }

    //隐藏遮罩层
    function hide(target) {
        var state = $.data(target, 'mask');
        state.showCount--;
       	state.showCount = Math.max(state.showCount, 0); //最小为0
        if (state.showCount <= 0) {
            var mask = state.mask;
            var maskMsg = state.maskMsg;
            $('select.x-mask-disabled-select').removeAttr('disabled');
            mask.css('display', 'none');
            maskMsg.css('display', 'none');
        }
    }

    //销毁遮罩层
    function destroy(target) {
        var state = $.data(target, 'mask');
        var mask = state.mask;
        var maskMsg = state.maskMsg;
        $('select.x-mask-disabled-select').removeClass('x-mask-disabled-select').removeAttr('disabled');
        mask.remove();
        maskMsg.remove();
        $(target).removeData('mask');
    }

    function getPageArea() {
        return {
            width: Math.max(document.body.clientWidth, document.documentElement.clientWidth),
            height: Math.max(document.body.clientHeight, document.documentElement.clientHeight)
        }
    }

    //遮罩层
    $.fn.mask = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.mask.methods[options](this, param);
        }
        options = options || {};

        return this.each(function() {
            var state = $.data(this, 'mask');
            var opts;
            if (state) {
                opts = $.extend(state.options, options);
            } else {
                opts = $.extend({}, $.fn.mask.defaults, options);
                $.data(this, 'mask', {
                    showCount: 0,
                    options: opts
                });

                init(this);
            }

            if (opts.hide) {
                hide(this);
            } else {
                show(this);
            }

			setSize(this);
            bindEvents(this);
        });
    };

    $.fn.mask.methods = {
        show: function(jq) {
            jq.each(function() {
                show(this);
            });
        },
        hide: function(jq) {
            jq.each(function() {
                hide(this);
            });
        },
        destroy: function(jq) {
            jq.each(function() {
                destroy(this);
            });
        }
    }

    $.fn.mask.defaults = {
        msg: '处理中，请稍候',
        hide: false
    }
})(jQuery);
/**
 * accordion - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
	
	function bindEvents(target) {
		var t = $(target);
		var state = $.data(target, 'accordion');
		var opts = state.options;
		
		t.find('>div.accordion-group>div.accordion-heading>a.accordion-toggle').unbind('.accordion').bind('click.accordion', function(){
			var bId = $(this).attr('href');
			var b = $(bId);
			
			if(b.hasClass('in')) {
				b.removeClass('in');
			} else {
				b.addClass('in');
			}
			
			if(!opts.multiple) {
				t.find('>div.accordion-group>div.accordion-body').not(b).removeClass('in');
			}
		});
	}
	
    $.fn.accordion = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.accordion.methods[options](this, param);
        }
        options = options || {};
        return this.each(function() {
            var opts;
            var state = $.data(this, 'accordion');
            if (state) {
                opts = $.extend(state.options, options);
            } else {
                opts = $.extend({}, $.fn.accordion.defaults, $.fn.accordion.parseOptions(this), options);
                $.data(this, 'accordion', {
                    options: opts
                });
            }
            
            bindEvents(this);
        });
    };

    $.fn.accordion.methods = {
        options: function(jq) {
            return $.data(jq[0], 'accordion').options;
        }        
    };

    $.fn.accordion.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target));
    };

    $.fn.accordion.defaults = {
        multiple: true
    };

})(jQuery);/**
 * tabs - jQuery xui
 *
 * Licensed under the GPL: http://www.gnu.org/licenses/gpl.txt
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {

    function bindEvents(target) {
        var t = $(target);
        var state = $.data(target, 'tabs');
        var opts = state.options;

        t.find('>li>a').unbind('.tabs').bind('click.tabs', function() {
        	var a = $(this);
            var pId = a.attr('href');
            var p = $(pId);
			
			a.parent().parent().find('>li').removeClass('active');
			p.parent().find('>div.tab-pane').removeClass('active');
			a.parent().addClass('active');
			p.addClass('active');
        });
    }

    $.fn.tabs = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.tabs.methods[options](this, param);
        }

        options = options || {};

        return this.each(function() {
            var state = $.data(this, 'tabs');
            var opts;
            if (state) {
                opts = $.extend(state.options, options);
            } else {
                opts = $.extend({}, $.fn.tabs.defaults, $.fn.tabs.parseOptions(this), options);
                $.data(this, 'tabs', {
                    options: opts
                });
            }

            bindEvents(this);
        });
    };

    $.fn.tabs.methods = {};

    $.fn.tabs.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target));
    };

    $.fn.tabs.defaults = {};
})(jQuery);/**
 * pagination - jQuery xui
 *
 * Licensed under the GPL:
 *   http://www.gnu.org/licenses/gpl.txt
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    /**
     * 绑定事件
     */
    function bindEvents(target) {
        var opts = $.data(target, 'pagination').options;
        var pager = $(target);

        $('a.x-pagination-first', pager).unbind('.pagination').bind('click.pagination', function() {
            if (opts.pageNumber > 1) {
                selectPage(target, 1);
            }
        });
        $('a.x-pagination-prev', pager).unbind('.pagination').bind('click.pagination', function() {
            if (opts.pageNumber > 1) {
                selectPage(target, opts.pageNumber - 1);
            }
        });
        $('a.x-pagination-next', pager).unbind('.pagination').bind('click.pagination', function() {
            var pageCount = Math.ceil(opts.total / opts.pageSize);
            if (opts.pageNumber < pageCount) {
                selectPage(target, opts.pageNumber + 1);
            }
        });
        $('a.x-pagination-last', pager).unbind('.pagination').bind('click.pagination', function() {
            var pageCount = Math.ceil(opts.total / opts.pageSize);
            if (opts.pageNumber < pageCount) {
                selectPage(target, pageCount);
            }
        });
        $('a.x-pagination-reload', pager).unbind('.pagination').bind('click.pagination', function() {
            selectPage(target, opts.pageNumber);
        });
        
        $('select.x-pagination-page-list', pager).unbind('.pagination').bind('change.pagination', function() {
            opts.pageSize = $(this).val();
            selectPage(target, opts.pageNumber);
        });
    }

    function selectPage(target, pageNumber) {
        var opts = $.data(target, 'pagination').options;
        var pageCount = Math.ceil(opts.total / opts.pageSize);
        if (pageNumber > pageCount) pageNumber = pageCount;
        if (pageNumber < 1) pageNumber = 1; //页码最小是1
        opts.onSelectPage.call(target, pageNumber, opts.pageSize);
        opts.pageNumber = pageNumber;
        showPagerInfo(target);
    }

    function showPagerInfo(target) {
        var opts = $.data(target, 'pagination').options;
        var pager = $(target);
        var pageCount = Math.ceil(opts.total / opts.pageSize);

        if (pageCount < 1) { //总页码数最小是1
            pageCount = 1;
        }
        $('.x-pagination-info', pager).text(opts.displayMsg.replace(/{page}/, opts.pageNumber).replace(/{pages}/, pageCount).replace(/{total}/, opts.total));
        $('.x-pagination-first,.x-pagination-prev', pager).parent().removeClass('disabled').addClass((opts.pageNumber == 1) ? 'disabled' : '');
        $('.x-pagination-next,.x-pagination-last', pager).parent().removeClass('disabled').addClass((opts.pageNumber == pageCount) ? 'disabled' : '');
    }

    $.fn.pagination = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.pagination.methods[options](this, param);
        }

        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'pagination');
            var opts;
            if (state) {
                opts = $.extend(state.options, options);
            } else {
                opts = $.extend({}, $.fn.pagination.defaults, $.fn.pagination.parseOptions(this), options);
                $.data(this, 'pagination', {
                    options: opts
                });
            }
            bindEvents(this);
            showPagerInfo(this);
        });
    };

    $.fn.pagination.methods = {
        options: function(jq) {
            return $.data(jq[0], "pagination").options;
        },
        select: function(jq, param) {
            return jq.each(function() {
                selectPage(this, param);
            });
        }
    };

    $.fn.pagination.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target));
    };

    $.fn.pagination.defaults = {
        total: 0,
        pageSize: 10,
        pageNumber: 1,
        displayMsg: '第{page}页/共{pages}页,共{total}条记录',
        onSelectPage: function(pageNumber, pageSize) {},
        onChangePageSize: function(pageSize) {}
    };
})(jQuery);
/**
 * datagrid - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 * 依赖
 *	 pagination
 */
(function($) {
    /**
     * 包裹<table>,返回{columns}
     */
    function wrapGrid(target) {
        var columns = getColumns($('thead', target));

        function getColumns(thead) {
            var columns = [];
            $('tr', thead).each(function() {
                var cols = [];
                $('th', this).each(function() {
                    var th = $(this);

                    var col = $.extend({
                        title: th.html()
                    }, $.parser.parseOptions(this, [
                        'align', 'width', {
                            rowspan: 'number',
                            colspan: 'number'
                        }
                    ]));

                    cols.push(col);
                });
                columns.push(cols);
            });

            return columns;
        }

        return {
            columns: columns
        };
    }
    /**
     *构建body
     */
    function buildBody(target, rows) {
        var opts = $.data(target, 'datagrid').options;
        var fields = getColumnFields(opts.columns);


        var body = [];
        for (var i = 0; i < opts.pageSize && i < rows.length; i++) {
            var row = rows[i];
            if (i % 2 && opts.striped) {
                body.push('<tr x-datagrid-row-index="' + i + '" class="info">');
            } else {
                body.push('<tr x-datagrid-row-index="' + i + '">');
            }

			var rownumber = i + 1;
            if (opts.pagination) {
                rownumber += (opts.pageNumber - 1) * opts.pageSize;
            }
            
            for (var j = 0; j < fields.length; j++) {
                var field = fields[j];
                var col = getColumnOption(opts.columns, field);
                if (col) {
                	if (col.rownumber) {
                        body.push('<td class="x-datagrid-cell-rownumber">');
                    } else if (col.checkbox) {
                        body.push('<td class="x-datagrid-cell-check">');
                    } else {
                    	body.push('<td field="' + field + '">');
                    }
					
					if (col.rownumber) {
                        body.push(rownumber);
                    } else if (col.checkbox) {
                        body.push('<input type="checkbox"/>');
                    } else if (col.formatter) {
                        body.push(col.formatter(row[field], row, i));
                    } else {
                        body.push(row[field]);
                    }
                    body.push('</td>');
                }
            }
            body.push('</tr>');
        }

        $('>tbody', target).html(body.join(''));
    }

    /**
     *构建pagination
     */
    function buildPagination(target) {
        var state = $.data(target, 'datagrid');
        var opts = state.options;

        if (opts.pagination) {
            var pager = $(opts.pagination);
            pager.pagination({
                pageNumber: opts.pageNumber,
                pageSize: opts.pageSize,
                onSelectPage: function(pageNum, pageSize) {
                    // 保存分页状态
                    opts.pageNumber = pageNum;
                    opts.pageSize = pageSize;
        
                    request(target); // 请求远程数据
                }
            });
        }
    }

    /**
     * 绑定事件
     */
    function bindEvents(target) {
        var opts = $.data(target, 'datagrid').options;
        var data = $.data(target, 'datagrid').data;
        //body事件
        $('>tbody>tr>td.x-datagrid-cell-check>input[type="checkbox"]', target).unbind('.datagrid').bind('click.datagrid', function(e) {
            e.stopPropagation();
        });

        $('>tbody>tr', target).unbind('.datagrid').bind('click.datagrid', function() {
            var index = $(this).attr('x-datagrid-row-index');
            if (!$(this).hasClass('success')) {
                selectRow(target, index);
            }

            if (opts.onClickRow) {
                opts.onClickRow.call(this, index, data.rows[index]);
            }
        });

        //header事件
        $('>thead>tr>th.x-datagrid-cell-check>input[type="checkbox"]', target).unbind('.datagrid').bind('click.datagrid', function() {
            if ($(this).prop('checked')) {
                $('>tbody>tr>td.x-datagrid-cell-check>input[type="checkbox"]', target).prop('checked', true);
            } else {
                $('>tbody>tr>td.x-datagrid-cell-check>input[type="checkbox"]', target).prop('checked', false);
            }
        });
    }

    /**
     * 根据field获取对应field的选项
     */
    function getColumnOption(columns, field) {
        if (columns) {
            for (var i = 0; i < columns.length; i++) {
                var cols = columns[i];
                for (var j = 0; j < cols.length; j++) {
                    var col = cols[j];
                    if (col.field == field) {
                        return col;
                    }
                }
            }
        }
        return null;
    }

    /**
     * 获取fields
     */
    function getColumnFields(columns) {
        if (columns.length == 0) return [];

        function getFields(ridx, cidx, count) {
            var fields = [];
            while (fields.length < count) {
                var col = columns[ridx][cidx];
                if (col.colspan && col.colspan > 1) {
                    var ff = getFields(ridx + 1, getSubColIndex(ridx, cidx), col.colspan);
                    fields = fields.concat(ff);
                } else if (col.field) {
                    fields.push(col.field);
                }
                cidx++;
            }

            return fields;
        }

        function getSubColIndex(ridx, cidx) {
            var index = 0;
            for (var i = 0; i < cidx; i++) {
                var colspan = columns[ridx][i].colspan || 1;
                if (colspan > 1) {
                    index += colspan;
                }
            }
            return index;
        }

        var fields = [];
        for (var i = 0; i < columns[0].length; i++) {
            var col = columns[0][i];
            if (col.colspan && col.colspan > 1) {
                var ff = getFields(1, getSubColIndex(0, i), col.colspan);
                fields = fields.concat(ff);
            } else if (col.field) {
                fields.push(col.field);
            }
        }

        return fields;
    }

    /**
     * 获取colspan
     */
    function getColumnColspan(columns) {
        var column = columns[0];
        var colspan = 0;
        for (var i = 0; i < column.length; i++) {
            colspan += (column[i].colspan || 1);
        }
        return colspan;
    }

    /**
     * 加载数据
     */
    function loadData(target, data) {
        var state = $.data(target, 'datagrid');
        var opts = state.options;
        
        //数组数据处理
        if ($.isArray(data)) {
            data = {
                rows: data,
                total: data.length
            }
        } else {
            data.total = parseInt(data.total); //防止total是字符串
        }
        buildBody(target, data.rows);
        state.data = data;

		if(opts.pagination) {
	        $(opts.pagination).pagination({
	            total: data.total
	        });
    	}
        bindEvents(target);
    }

    /**
     * 获取checked记录
     */
    function getCheckedRows(target) {
        var state = $.data(target, 'datagrid');
        var data = state.data;

        var rows = [];
        $('>tbody>tr>td.x-datagrid-cell-check>input[type="checkbox"]:checked', target).parent().parent().each(function() {
            var index = parseInt($(this).attr('x-datagrid-row-index'));
            if (data.rows[index]) {
                rows.push(data.rows[index]);
            }
        });
        return rows;
    };

    /**
     * 获取selected记录
     */
    function getSelectedRows(target) {
        var state = $.data(target, 'datagrid');
        var data = state.data;

        var rows = [];
        $('>tbody>tr.success', target).each(function() {
            var index = parseInt($(this).attr('x-datagrid-row-index'));
            if (data.rows[index]) {
                rows.push(data.rows[index]);
            }
        });
        return rows;
    }

    /**
     * 清除全部选中记录
     */
    function clearSelections(target) {
        $('>tbody>tr.success', target).removeClass('success');
        $('>tbody>tr>td.x-datagrid-cell-check>input[type="checkbox"]', target).prop('checked', false);
    }

    /**
     * 根据索引选中记录,索引从这0开始
     */
    function selectRow(target, index) {
        var opts = $.data(target, 'datagrid').options;
        var data = $.data(target, 'datagrid').data;

        var tr = $('>tbody>tr[x-datagrid-row-index="' + index + '"]', target);
        clearSelections(target);
        tr.addClass('success');

        opts.onSelect.call(target, index, data.rows[index]);
    }

    /**
     * 请求远程数据
     */
    function request(target) {
        var state = $.data(target, 'datagrid');
        var opts = state.options;
        var grid = state.grid;

        if (!opts.url) {
            return false;
        }

        var param = $.extend({}, opts.queryParams);
        if (opts.pagination) {
            $.extend(param, {
                page: opts.pageNumber,
                rows: opts.pageSize
            });
        }

        $.ajax({
            type: opts.method,
            url: opts.url,
            data: param,
            dataType: 'json',
            success: function(data) {
                loadData(target, data);
                if (opts.onLoadSuccess) {
                    opts.onLoadSuccess.apply(this, arguments);
                }
            }
        });
    }

    $.fn.datagrid = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.datagrid.methods[options](this, param);
        }

        options = options || {};

        return this.each(function() {
            var state = $.data(this, 'datagrid');
            var opts;
            if (state) {
                opts = $.extend(state.options, options);
            } else {
                opts = $.extend({}, $.fn.datagrid.defaults, $.fn.datagrid.parseOptions(this), options);

                var wrapResult = wrapGrid(this);
                if (!opts.columns) {
                    opts.columns = wrapResult.columns;
                }
                $.data(this, 'datagrid', {
                    options: opts,
                    data: {
                        total: 0,
                        rows: []
                    }
                });
            }

            buildPagination(this);

            if (opts.data) {
                loadData(this, opts.data);
            }

            if (opts.url) {
                request(this);
            }

            bindEvents(this);
        });
    };

    $.fn.datagrid.methods = {
        options: function(jq) {
            return $.data(jq[0], 'datagrid').options;
        },
        reload: function(jq) {
            return jq.each(function() {
                request(this);
            });
        },
        loadData: function(jq, param) {
            return jq.each(function() {
                loadData(this, param);
            });
        },
        getData: function(jq) {
            return $.data(jq[0], "datagrid").data;
        },
        getChecked: function(jq) {
            return getCheckedRows(jq[0]);
        },
        getSelected: function(jq) {
            var rows = getSelectedRows(jq[0]);
            return rows.length > 0 ? rows[0] : null;
        },
        clearSelections: function(jq) {
            return jq.each(function() {
                clearSelections(this);
            });
        },
        selectRow: function(jq, param) {
            return jq.each(function() {
                selectRow(this, param);
            });
        }
    };

    $.fn.datagrid.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target, [
            'width', 'height', 'title'
        ]));
    };

    $.fn.datagrid.defaults = {
        title: '',
        iconCls: null,
        border: true,
        width: 'auto',
        height: 'auto',
        columns: null,
        striped: false, //条纹
        method: 'post',
        url: null,
        loadMsg: '正在处理，请稍待。。。',
        pagination: null,
        pageNumber: 1,
        pageSize: 10,
        queryParams: {},

        onLoadSuccess: function() {},
        onClickRow: function(rowIndex, rowData) {},
        onSelect: function(rowIndex, rowData) {}
    };
})(jQuery);
/**
 * dialog - jQuery xui
 *
 * Licensed under the GPL:
 *   http://www.gnu.org/licenses/gpl.txt
 *
 * Copyright 2013 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {

    $.fn.dialog = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.dialog.methods[options](this, param);
        }

        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'dialog');
            if (state) {
                $.extend(state.options, options);
            } else {
                state = $.data(this, 'dialog', {
                    options: $.extend({}, $.fn.dialog.defaults, $.fn.dialog.parseOptions(this), options)
                });
                if (!state.options.inline) {
                    document.body.appendChild(this);
                }
            }
            bindEvents(this);
        });
    };

    $.fn.dialog.methods = {
        options: function(jq) {
            return $.data(jq[0], 'dialog').options;
        }
    };

    $.fn.dialog.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target));
    };

    $.fn.dialog.defaults = {};
})(jQuery);/**
 * tooltip - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    function init(target) {
    };

    function bindEvents(target) {
        var opts = $.data(target, 'tooltip').options;
        $(target).unbind('.tooltip').bind(opts.showEvent + '.tooltip', function(e) {
            $(target).tooltip('show', e);
        }).bind(opts.hideEvent + '.tooltip', function(e) {
            $(target).tooltip('hide', e);
        });
    };

    function clearTimer(target) {
        var state = $.data(target, 'tooltip');
        if (state.showTimer) {
            clearTimeout(state.showTimer);
            state.showTimer = null;
        }
        if (state.hideTimer) {
            clearTimeout(state.hideTimer);
            state.hideTimer = null;
        }
    };

    function reposition(target) {
        var state = $.data(target, 'tooltip');
        if (!state || !state.tip) {
            return;
        }
        var opts = state.options;
        var tip = state.tip;
        var position = {
            left: -100000,
            top: -100000
        };
        if ($(target).is(':visible')) {
            position = calcPosition(opts.position);
        }
        tip.css({
            left: position.left,
            top: position.top,
            zIndex: (opts.zIndex != undefined ? opts.zIndex : '') //TODO
        });

        function calcPosition(position) {
            opts.position = position || 'bottom';
            tip.removeClass('top bottom left right').addClass(opts.position);
            var left, top;
            var t = $(target);
            left = t.offset().left + opts.deltaX;
            top = t.offset().top + opts.deltaY;
            switch (opts.position) {
                case 'right':
                    left += t._outerWidth() + 6;
                    top -= (tip._outerHeight() - t._outerHeight()) / 2;
                    break;
                case 'left':
                    left -= tip._outerWidth() + 6;
                    top -= (tip._outerHeight() - t._outerHeight()) / 2;
                    break;
                case 'top':
                    left -= (tip._outerWidth() - t._outerWidth()) / 2;
                    top -= tip._outerHeight() + 6;
                    break;
                case 'bottom':
                    left -= (tip._outerWidth() - t._outerWidth()) / 2;
                    top += t._outerHeight() + 6;
                    break;
            }
            return {
                left: left,
                top: top
            };
        };
    };

    function show(target, e) {
        var state = $.data(target, 'tooltip');
        var opts = state.options;
        var tip = state.tip;
        if (!tip) {
            tip = $('<div class="tooltip" style="display: block;">'+
			'<div class="tooltip-arrow"></div>'+
			'<div class="tooltip-inner"></div>'+
			'</div>').appendTo('body');
            state.tip = tip;
            updateContent(target);
        }
        clearTimer(target);
        state.showTimer = setTimeout(function() {
            reposition(target);
            tip.addClass('in');
            opts.onShow.call(target, e);
        }, opts.showDelay);
    };

    function hide(target, e) {
        var state = $.data(target, 'tooltip');
        if (state && state.tip) {
            clearTimer(target);
            state.hideTimer = setTimeout(function() {
                state.tip.removeClass('in');
                state.options.onHide.call(target, e);
            }, state.options.hideDelay);
        }
    };

    function updateContent(target, content) {
        var state = $.data(target, 'tooltip');
        var opts = state.options;
        if (content) {
            opts.content = content;
        }
        if (!state.tip) {
            return;
        }
        state.tip.find('>.tooltip-inner').html(opts.content);
        opts.onUpdate.call(target, opts.content);
    };

    function destroy(target) {
        var state = $.data(target, 'tooltip');
        if (state) {
            clearTimer(target);
            var opts = state.options;
            if (state.tip) {
                state.tip.remove();
            }
            $.removeData(target, 'tooltip');
            $(target).unbind('.tooltip');
            opts.onDestroy.call(target);
        }
    };
    $.fn.tooltip = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.tooltip.methods[options](this, param);
        }
        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'tooltip');
            if (state) {
                $.extend(state.options, options);
            } else {
                $.data(this, 'tooltip', {
                    options: $.extend({}, $.fn.tooltip.defaults, $.fn.tooltip.parseOptions(this), options)
                });
                init(this);
            }
            bindEvents(this);
            updateContent(this);
        });
    };
    $.fn.tooltip.methods = {
        options: function(jq) {
            return $.data(jq[0], 'tooltip').options;
        },
        tip: function(jq) {
            return $.data(jq[0], 'tooltip').tip;
        },
        show: function(jq, e) {
            return jq.each(function() {
                show(this, e);
            });
        },
        hide: function(jq, e) {
            return jq.each(function() {
                hide(this, e);
            });
        },
        update: function(jq, content) {
            return jq.each(function() {
                update(this, content);
            });
        },
        destroy: function(jq) {
            return jq.each(function() {
                destroy(this);
            });
        }
    };
    $.fn.tooltip.parseOptions = function(target) {
        return opts = $.extend({}, $.parser.parseOptions(target));
    };
    $.fn.tooltip.defaults = {
        position: 'bottom',
        content: null,
        deltaX: 0,
        deltaY: 0,
        showEvent: 'mouseenter',
        hideEvent: 'mouseleave',
        showDelay: 100,
        hideDelay: 100,
        onShow: function(e) {},
        onHide: function(e) {},
        onUpdate: function(content) {},
        onDestroy: function() {}
    };
})(jQuery);
/**
 * select2 - jQuery xui
 *
 * Licensed under the GPL:
 *   http://www.gnu.org/licenses/gpl.txt
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    function setDisabled(target, disabled) {
    	var state = $.data(target, 'select2');
        var opts = state.options;
        if (disabled) {
            opts.disabled = true;
            $(target).attr('disabled', 'disabled');
        } else {
            opts.disabled = false;
            $(target).removeAttr('disabled');
        }
    }

    //获取值
    function getValue(target) {
        return $(target).val();
    }

    //设置值
    function setValue(target, value) {
        $(target).val(value);
    }

    //加载数据
    function loadData(target, data) {
        var state = $.data(target, 'select2');
        var opts = state.options;
        state.data = opts.loadFilter.call(target, data);
        data = state.data;

        var dd = ['<option value="">--请选择--</option>'];
        for (var i = 0; i < data.length; i++) {
            var item = data[i];
            var v = item[opts.valueField];
            var s = item[opts.textField];

            dd.push('<option value="' + v + '">');
            dd.push(opts.formatter ? opts.formatter.call(target, item) : s);
            dd.push('</option>');
        }
        target.innerHTML = dd.join('');
        opts.onLoadSuccess.call(target, data);
    }

    //请求远程数据
    function request(target, url, param) {
        var opts = $.data(target, 'select2').options;
        if (url) {
            opts.url = url;
        }
        if (!opts.url)
            return;
        param = param || {};

        if (opts.onBeforeLoad.call(target, param) == false)
            return;

        $.ajax({
            type: opts.method,
            url: opts.url,
            data: param,
            dataType: 'json',
            success: function(data) {
                loadData(target, data);
            },
            error: function() {
                opts.onLoadError.apply(this, arguments);
            }
        });
    }

    $.fn.select2 = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.select2.methods[options](this, param);
        }

        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'select2');
            var opts;
            
            if (state) {
                opts = $.extend(state.options, options);
            } else {
                opts = $.extend({}, $.fn.select2.defaults, $.fn.select2.parseOptions(this), options);
                state = $.data(this, 'select2', {
                    options: opts,
                    data: []
                });
            }
            
            if (opts.data) {
                loadData(this, opts.data);
            }
            request(this);

            setDisabled(this, opts.disabled);
        });
    };


    $.fn.select2.methods = {
        options: function(jq) {
            return $.data(jq[0], 'select2').options;
        },
        getData: function(jq) {
            return $.data(jq[0], 'select2').data;
        },
        getValue: function(jq) {
            return getValue(jq[0]);
        },
        setValue: function(jq, value) {
            return jq.each(function() {
                setValue(this, [value]);
            });
        },
        disable: function(jq) {
            return jq.each(function() {
                setDisabled(this, true);
            });
        },
        enable: function(jq) {
            return jq.each(function() {
                setDisabled(this, false);
            });
        },
        clear: function(jq) {
            return jq.each(function() {
                //                
            });
        },
        loadData: function(jq, data) {
            return jq.each(function() {
                loadData(this, data);
            });
        },
        reload: function(jq, url) {
            return jq.each(function() {
                request(this, url);
            });
        }
    };

    $.fn.select2.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target));
    };

    $.fn.select2.defaults = {
        valueField: 'value',
        textField: 'text',
        mode: 'local', // or 'remote'
        method: 'post',
        url: null,
        data: null,
        formatter: function(row) {
            var opts = $(this).select2('options');
            return row[opts.textField];
        },
        loadFilter: function(data) {
            return data;
        },
        onBeforeLoad: function(param) {},
        onLoadSuccess: function() {},
        onLoadError: function() {}
    };
})(jQuery);
/**
 * validatebox - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {

    function init(target) {
        $(target).addClass('x-validatebox-text');
    }

    function destroyBox(target) {
        var state = $.data(target, 'validatebox');
        if (state.timer) {
            clearTimeout(state.timer);
        }
        
        $(target).tooltip('destroy');
        $(target).unbind('.validatebox');
        $(target).removeData('validatebox');
    }

    function bindEvents(target) {
        var box = $(target);
        var state = $.data(target, 'validatebox');

        if (state.timer) {
            clearTimeout(state.timer);
            state.timer = undefined;
        }
        box.unbind('.validatebox');
        if (state.options.novalidate) {
            return;
        }
        box.bind('focus.validatebox', function() {
            state.validating = true;
            state.value = undefined;
            (function() {
                if (state.validating) {
                    if (state.value != box.val()) {
                        state.value = box.val();
                        if (state.timer) {
                            clearTimeout(state.timer);
                        }
                        state.timer = setTimeout(function() {
                            validate(target);
                        }, state.options.delay);
                    }
                    setTimeout(arguments.callee, 200);
                }
            })();
        }).bind('blur.validatebox', function() {
            if (state.timer) {
                clearTimeout(state.timer);
                state.timer = undefined;
            }
            state.validating = false;
            validate(this);
        }).bind('mouseover.validatebox', function() {
            if (box.hasClass('x-validatebox-invalid')) {
                showTip(target);
            }
        }).bind('mouseout.validatebox', function() {
            if (!state.validating) {
                hideTip(target);
            }
        });
    }

    function showTip(target) {
        var state = $.data(target, 'validatebox');
        var opts = state.options;
        $(target).tooltip($.extend({}, opts.tipOptions, {
            content: state.message,
            position: opts.tipPosition,
            deltaX: opts.deltaX
        })).tooltip('show');
        state.tip = true;
    }

    /**
     * 隐藏提示信息
     */
    function hideTip(target) {
        var state = $.data(target, 'validatebox');
        state.tip = false;
        $(target).tooltip('hide');
    }

    /**
     * 验证
     */
    function validate(target) {
        var state = $.data(target, 'validatebox');
        var opts = state.options;
        var tip = state.tip;
        var box = $(target);
        var value = box.val();

        function setTipMessage(msg) {
            $.data(target, 'validatebox').message = msg;
        }

        if (opts.novalidate || box.is(':disabled')) {
            return true;
        }

        if (opts.required) {
            if (value === '' || value === null) {
                box.addClass('x-validatebox-invalid');
                setTipMessage(opts.missingMessage);
                showTip(target);
                return false;
            }
        }
        if (opts.validType) {
            var result = /([a-zA-Z_]+)(.*)/.exec(opts.validType);
            var rule = opts.rules[result[1]];
            if (value && rule) {
                var param = eval(result[2]);
                if (!rule['validator'](value, param)) {
                    box.addClass('x-validatebox-invalid');

                    var message = rule['message'];
                    if (param) {
                        for (var i = 0; i < param.length; i++) {
                            message = message.replace(new RegExp('\\{' + i + '\\}', 'g'), param[i]);
                        }
                    }
                    setTipMessage(opts.invalidMessage || message);
                    showTip(target);
                    return false;
                }
            }
        }

        box.removeClass('x-validatebox-invalid');
        hideTip(target);
        return true;
    }

    /**
     * 是否禁用验证
     */
    function disableValidate(target, disable) {
        var opts = $.data(target, 'validatebox').options;
        if (disable != undefined) {
            opts.novalidate = disable;
        }
        if (opts.novalidate) {
            $(target).removeClass('x-validatebox-invalid');
            hideTip(target);
        }
        bindEvents(target);
    };

    $.fn.validatebox = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.validatebox.methods[options](this, param);
        }

        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'validatebox');
            if (state) {
                $.extend(state.options, options);
            } else {
                $.data(this, 'validatebox', {
                    options: $.extend({}, $.fn.validatebox.defaults, $.fn.validatebox.parseOptions(this), options)
                });
                init(this);
            }
            bindEvents(this);
        });
    };

    $.fn.validatebox.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target));
    };

    $.fn.validatebox.methods = {
        destroy: function(jq) {
            return jq.each(function() {
                destroyBox(this);
            });
        },
        validate: function(jq) {
            return jq.each(function() {
                validate(this);
            });
        },
        isValid: function(jq) {
            return validate(this[0]);
        },
        enableValidation: function(jq) {
            return jq.each(function() {
                disableValidate(this, false);
            });
        },
        disableValidation: function(jq) {
            return jq.each(function() {
                disableValidate(this, true);
            });
        }
    };

    $.fn.validatebox.defaults = {
        required: false,
        validType: null,
        delay: 200,
        missingMessage: '该输入项为必输项',
        invalidMessage: null,
        novalidate: false,
        tipPosition: 'right',
        deltaX: 0,
        tipOptions: {
        	showEvent: 'none',
            hideEvent: 'none',
            showDelay: 0,
            hideDelay: 0,
            zIndex: '',
            onShow: function() {
                $(this).tooltip('tip').css({
                    color: '#000',
                    borderColor: '#CC9933',
                    backgroundColor: '#FFFFCC'
                });
            }
        },
        rules: {
            email: {
                validator: function(value) {
                    return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
                },
                message: '请输入有效的电子邮件地址'
            },
            url: {
                validator: function(value) {
                    return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
                },
                message: '请输入有效的URL地址'
            },
            length: {
                validator: function(value, param) {
                    var len = $.trim(value).length;
                    return len >= param[0] && len <= param[1]
                },
                message: '输入内容长度必须介于{0}和{1}之间'
            }
        }
    };
})(jQuery);
/**
 * combobox - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 */
(function($) {
    
    function init(target) {
    	var state = $.data(target, 'combobox');
        var panel = $('<ul class="x-combobox-panel"></ul>').appendTo('body');
        
		state.panel = panel;
    }

    function setSize(target) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        var panel = state.panel;
        
        var t = $(target);
		
		panel._outerWidth(t.width()).css({
			zIndex: opts.zIndex
		});
    }

    function bindEvents(target) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        var panel = state.panel;
        
        var t = $(target);
        var input = t.children('.x-combobox-text');
        var arrow = t.children('.x-combobox-arrow');

        //全局事件
        $(document).unbind('.combobox').bind('mousedown.combobox', function(e) {
            //隐藏没有击中的combobox的下拉面板
            var p = $(e.target).closest('ul.x-combobox-panel');
            var panels = $('body>ul.x-combobox-panel:visible');
            if (p.length) {
                panels = panels.not(p[0]);
            }
            p = $(e.target).closest('.x-combobox');
            if (p.length) {
                p = p.combobox('panel');
                panels = panels.not(p);
            }
            panels.css('display', 'none');
        });

        //先取消绑定事件
        t.unbind('.combobox');
        input.unbind('.combobox');
        arrow.unbind('.combobox');

        if (!opts.disabled) {
        	input.bind('click.combobox', function(e) {
	            togglePanel(target);
	        }).bind('keydown.combobox', function(e) {
                switch (e.keyCode) {
                    case 37: //left
                    case 38: //up
                        nav(target, 'prev');
                        break;
                    case 39: //right
                    case 40: //down
                        nav(target, 'next');
                        break;
                    case 13: //enter
                        onEnter(target);
                        break;
                    case 9: //tab
                    case 27: //esc
                        hidePanel(target);
                        break;
                    default:
                        if (state.timer) {
                            clearTimeout(state.timer);
                        }
                        state.timer = setTimeout(function() {
                            var q = input.val();
                            if (state.previousValue != q) {
                                state.previousValue = q;
                                showPanel(target);
                                onQuery(target, q);
                            }
                        }, opts.delay);
                        break;
                }
            });
            
            //下拉箭头
            arrow.bind('click.combobox', function() {
                //聚焦且光标放到文本最后
                input.focus().val(input.val());
                togglePanel(target);
            });
            
            //下拉选项
            panel.children('li.x-combobox-item').unbind('.combobox').bind('mouseover.combobox', function() {
                $(this).addClass('x-combobox-item-hover');
            }).bind('mouseout.combobox', function() {
                $(this).removeClass('x-combobox-item-hover');
            }).bind('click.combobox', function(e) {
                var value = $(this).attr('value');
                select(target, value);
                hidePanel(target);
            });
        }
    }

    //显示下拉面板
    function showPanel(target) {
        var state = $.data(target, 'combobox');
        var panel = state.panel;
        var t = $(target);
		
        panel.css({
            left: t.offset().left,
            top: t.offset().top + t.outerHeight(),
            display: 'block'
        });
        
        console.log($(target).combobox('getValue'));
        scrollTo(target, $(target).combobox('getValue'));
    }

    //隐藏下拉面板
    function hidePanel(target) {
        var panel = $.data(target, 'combobox').panel;
        panel.css('display', 'none');
    }

    //切换下拉面板
    function togglePanel(target) {
        var panel = $.data(target, 'combobox').panel;

        if (panel.is(':visible')) {
            hidePanel(target);
        } else {
            showPanel(target);
        }
    }

    function findDataItem(data, key, value) {
        for (var i = 0; i < data.length; i++) {
            var item = data[i];
            if (item[key] == value) {
                return item
            }
        }
        return null;
    }

    function scrollTo(target, value) {
        var state = $.data(target, 'combobox');
        var panel = state.panel;
		
		var item = panel.children('li.x-combobox-item[value="' + value + '"]');
        var item = panel.children('li.x-combobox-item[value="' + value + '"]');
        if (item.length) {
            if (item.position().top <= 0) {
                var h = panel.scrollTop() + item.position().top;
                panel.scrollTop(h);
            } else if (item.position().top + item.outerHeight() > panel.height()) {
                var h = panel.scrollTop() + item.position().top + item.outerHeight() - panel.height();
                panel.scrollTop(h);
            }
        }
    }

    function nav(target, dir) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        var panel = state.panel;

        var item = panel.children('li.x-combobox-item-hover');
        if (!item.length) {
            item = panel.children('li.x-combobox-item-selected');
        }
        item.removeClass('x-combobox-item-hover');
        if (!item.length) {
            item = panel.children('li.x-combobox-item:visible:' + (dir == 'next' ? 'first' : 'last'));
        } else {
            if (dir == 'next') {
                item = item.nextAll('li.x-combobox-item:visible:first');
                if (!item.length) {
                    item = panel.children('li.x-combobox-item:visible:first');
                }
            } else {
                item = item.prevAll('li.x-combobox-item:visible:first');
                if (!item.length) {
                    item = panel.children('li.x-combobox-item:visible:last');
                }
            }
        }
        
        if (item.length) {
            item.addClass('x-combobox-item-hover');
            scrollTo(target, item.attr('value'));
        }
    }

    function select(target, value) {
    	var state = $.data(target, 'combobox');
        var opts = state.options;
        var data = state.data;

        setValue(target, value);

        var item = findDataItem(data, opts.valueField, value);
        if (item) {
            opts.onSelect.call(target, item);
        }
    }

    function setDisabled(target, disabled) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        
        var t = $(target);

        if (disabled) {
            opts.disabled = true;
            t.children('input.x-combobox-text').attr('disabled', 'disabled');
        } else {
            opts.disabled = false;
            t.children('input.x-combobox-text').removeAttr('disabled');
        }
    }

    function getValue(target) {
        var state = $.data(target, 'combobox');
        
        var t = $(target);
        return t.children('input.x-combobox-value').val();
    }

    function setValue(target, value) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        var data = state.data;
        var panel = state.panel;
        
        var t = $(target);

        panel.children('li.x-combobox-item-selected').removeClass('x-combobox-item-selected');

        var item = findDataItem(data, opts.valueField, value);
        var text;
        if (item) {
            text = item[opts.textField];
        }
        panel.children('li.x-combobox-item[value="' + value + '"]').addClass('x-combobox-item-selected');
        //值
        t.children('input.x-combobox-value').val(value);
        //文本
        t.children('input.x-combobox-text').val(text);
    }

    //加载数据
    function loadData(target, data) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        var panel = state.panel;
        state.data = opts.loadFilter.call(target, data);
        data = state.data;

        var dd = [];
        for (var i = 0; i < data.length; i++) {
            var item = data[i];
            var v = item[opts.valueField];
            var s = item[opts.textField];

            dd.push('<li class="x-combobox-item" value="' + v + '">');
            dd.push(opts.formatter ? opts.formatter.call(target, item) : s);
            dd.push('</li>');
        }
        
        panel.html(dd.join(''));

        opts.onLoadSuccess.call(target, data);
    }

    //请求远程数据
    function request(target, url, param) {
        var opts = $.data(target, 'combobox').options;
        if (url) {
            opts.url = url;
        }
        if (!opts.url)
            return;
        param = param || {};

        if (opts.onBeforeLoad.call(target, param) == false)
            return;

        $.ajax({
            type: opts.method,
            url: opts.url,
            data: param,
            dataType: 'json',
            success: function(data) {
                loadData(target, data);
            },
            error: function() {
                opts.onLoadError.apply(this, arguments);
            }
        });
    }

    function onQuery(target, q) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        var data = state.data;
        var panel = state.panel;
        
         var t = $(target);

        if (opts.mode == 'remote') {
            request(target, null, {
                q: q
            }, true);
        } else {
            panel.children('li.x-combobox-item').hide();
            for (var i = 0; i < data.length; i++) {
                var item = data[i];
                if (opts.filter.call(target, q, item)) {
                    var v = item[opts.valueField];
                    panel.children('li.x-combobox-item[value="' + v + '"]').show();
                }
            }
        }
    }

    function onEnter(target) {
        var state = $.data(target, 'combobox');
        var opts = state.options;
        var data = state.data;
        var combo = state.combo;
        var panel = state.panel;

        var item = panel.children('li.x-combobox-item-hover');
        if (!item.length) {
            item = panel.children('li.x-combobox-item-selected');
        }
        if (!item.length) {
            return;
        }

        select(target, item.attr('value'));
        hidePanel(target);
    }

    $.fn.combobox = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.combobox.methods[options](this, param);
        }

        options = options || {};
        return this.each(function() {
            var state = $.data(this, 'combobox');
            var opts;
            if (state) {
                opts = $.extend(state.options, options);
            } else {
                opts = $.extend({}, $.fn.combobox.defaults, $.fn.combobox.parseOptions(this), options);
                state = $.data(this, 'combobox', {
                    options: opts,
                    data: []
                });
				init(this);                
            }
            if (options.data) {
                loadData(this, opts.data);
            }
            //request(this);

            //state.combo.find('.x-combobox-text').attr('readonly', !opts.editable);
            //setDisabled(this, opts.disabled);
            setSize(this);
            bindEvents(this);
        });
    };


    $.fn.combobox.methods = {
        options: function(jq) {
            return $.data(jq[0], 'combobox').options;
        },
        getData: function(jq) {
            return $.data(jq[0], 'combobox').data;
        },
        panel: function(jq) {
            return $.data(jq[0], 'combobox').panel;
        },
        getValue: function(jq) {
            return getValue(jq[0]);
        },
        setValue: function(jq, value) {
            return jq.each(function() {
                setValue(this, [value]);
            });
        },
        disable: function(jq) {
            return jq.each(function() {
                setDisabled(this, true);
                bindEvents(this);
            });
        },
        enable: function(jq) {
            return jq.each(function() {
                setDisabled(this, false);
                bindEvents(this);
            });
        },
        clear: function(jq) {
            return jq.each(function() {
                var panel = $.data(target, 'combobox').panel;
                panel.children('li.x-combobox-item-selected').removeClass('x-combobox-item-selected');
            });
        },
        loadData: function(jq, data) {
            return jq.each(function() {
                loadData(this, data);
            });
        },
        reload: function(jq, url) {
            return jq.each(function() {
                request(this, url);
            });
        },
        select: function(jq, value) {
            return jq.each(function() {
                select(this, value);
            });
        }
    };

    $.fn.combobox.parseOptions = function(target) {
        return $.extend({}, $.parser.parseOptions(target));
    };

    $.fn.combobox.defaults = {
    	zIndex: null,
        panelWidth: null,
        panelHeight: 200,
        disabled: false,
        valueField: 'value',
        textField: 'text',
        mode: 'local', // or 'remote'
        method: 'post',
        url: null,
        data: null,
        delay: 200,
        filter: function(q, row) {
            var opts = $(this).combobox('options');
            return row[opts.textField].indexOf(q) >= 0;
        },
        formatter: function(row) {
            var opts = $(this).combobox('options');
            return row[opts.textField];
        },
        loadFilter: function(data) {
            return data;
        },
        onBeforeLoad: function(param) {},
        onLoadSuccess: function() {},
        onLoadError: function() {},
        onSelect: function(record) {}
    };
})(jQuery);/**
 * form - jQuery xui
 *
 * Licensed under the Apache v2
 *
 * Copyright 2015 xjb [ beymy.en@gmail.com ]
 *
 * 依赖
 *   mask
 */
(function($) {
    /**
     * ajax提交表单
     */
    function ajaxSubmit(target, options) {
        options = options || {};

        if (options.onSubmit) {
            if (options.onSubmit.call(target) == false) {
                return;
            }
        }

        var form = $(target);
        if (!options.url) {
            options.url = form.attr('action');
        }

        form.mask().mask('show');
        $.ajax({
            type: 'POST',
            url: options.url,
            dataType: 'json',
            data: form.serialize(),
            success: function(data) {
                form.mask('hide');
                options.success.call(target, data);
            },
            error: function() {
                form.mask('hide');
            }
        });
    }

    /**
     * 加载表单数据
     * 如果data是string类型则代表URL,从远程加载数据
     * 否则加载本地object
     */
    function load(target, data) {
        if (typeof data == 'string') {
            $.ajax({
                url: data,
                dataType: 'json',
                success: function(data) {
                    _load(data);
                }
            });
        } else {
            _load(data);
        }

        function _load(data) {
            var form = $(target);
            for (var name in data) {
                var val = data[name];
                $('input[name="' + name + '"]', form).val(val);
                $('textarea[name="' + name + '"]', form).val(val);
                $('select[name="' + name + '"]', form).val(val);
                if ($.fn.combobox) {
                    $('select[comboboxName="' + name + '"]', form).combobox('setValue', val);
                }
            }
        }
    }

    /**
     * 清空表单
     */
    function clear(target) {
        $('input,select,textarea', target).each(function() {
            var t = this.type,
                tag = this.tagName.toLowerCase();
            if (t == 'text' || t == 'password' || tag == 'textarea')
                this.value = '';
            else if (t == 'checkbox' || t == 'radio')
                this.checked = false;
            else if (tag == 'select')
                this.selectedIndex = -1;

        });
    }

    /**
     * 重置表单
     */
    function reset(target) {
        target.reset();
    }

    /**
     * 验证表单
     */
    function validate(target) {
        if ($.fn.validatebox) {
            var t = $(target);
            t.find('.validatebox-text:not(:disabled)').validatebox('validate');
            var invalidbox = t.find('.validatebox-invalid');
            invalidbox.filter(':not(:disabled):first').focus();
            return invalidbox.length == 0;
        }
        return true;
    }

    $.fn.form = function(options, param) {
        if (typeof options == 'string') {
            return $.fn.form.methods[options](this, param);
        }
    };

    $.fn.form.methods = {
        submit: function(jq, options) {
            return jq.each(function() {
                ajaxSubmit(this, $.extend({}, $.fn.form.defaults, options || {}));
            });
        },
        load: function(jq, data) {
            return jq.each(function() {
                load(this, data);
            });
        },
        clear: function(jq) {
            return jq.each(function() {
                clear(this);
            });
        },
        reset: function(jq) {
            return jq.each(function() {
                reset(this);
            });
        },
        validate: function(jq) {
            return validate(jq[0]);
        }
    };

    $.fn.form.defaults = {
        url: null,
        onSubmit: function() {},
        success: function(data) {}
    };
})(jQuery);
